{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "source": [
    "# Interpreting the output of `find_adversarial_example`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Using the same example from the quickstart, we explore what information is available from the result of `find_adversarial_example`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: Method definition midpoints(Base.Range{T} where T) in module Base at deprecated.jl:56 overwritten in module StatsBase at /home/vtjeng/.julia/v0.6/StatsBase/src/hist.jl:535.\n",
      "WARNING: Method definition midpoints(AbstractArray{T, 1} where T) in module Base at deprecated.jl:56 overwritten in module StatsBase at /home/vtjeng/.julia/v0.6/StatsBase/src/hist.jl:533.\n"
     ]
    }
   ],
   "source": [
    "using MIPVerify\n",
    "using Gurobi\n",
    "using JuMP\n",
    "using Images\n",
    "\n",
    "mnist = MIPVerify.read_datasets(\"MNIST\")\n",
    "n1params = MIPVerify.get_example_network_params(\"MNIST.n1\")\n",
    "sample_image = MIPVerify.get_image(mnist.train.images, 1);\n",
    "\n",
    "function view_diff(diff::Array{<:Real, 2})\n",
    "    n = 1001\n",
    "    colormap(\"RdBu\", n)[ceil.(Int, (diff+1)/2*n)]\n",
    "end;"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Let's take a look at the output dictionary that results from a solve."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[36m[notice | MIPVerify]: Rebuilding model from scratch. This may take some time as we determine upper and lower bounds for the input to each non-linear unit. The model built will be cached and re-used for future solves, unless you explicitly set rebuild=false.\n",
      "\u001b[39m\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [10]\n",
      "\u001b[39m"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Dict{Symbol,Any} with 7 entries:\n",
       "  :PerturbationParameters => additive\n",
       "  :TargetIndexes          => [10]\n",
       "  :SolveStatus            => :Optimal\n",
       "  :Output                 => JuMP.GenericAffExpr{Float64,JuMP.Variable}[-0.0120…\n",
       "  :Model                  => Minimization problem with:…\n",
       "  :Perturbation           => JuMP.Variable[__anon__ __anon__ __anon__ __anon__ …\n",
       "  :PerturbedInput         => JuMP.Variable[__anon__ __anon__ __anon__ __anon__ …"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d1 = MIPVerify.find_adversarial_example(n1params, sample_image, 10, GurobiSolver(OutputFlag=0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:Model`\n",
    "\n",
    "The model stores a lot of information. (Remember not to try to print large models!) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true,
    "deletable": true,
    "editable": true
   },
   "outputs": [],
   "source": [
    "m = d1[:Model];"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Here are some methods you might find useful. [More on available methods](http://jump.readthedocs.io/en/latest/refmodel.html?highlight=model#methods)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3256"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "MathProgBase.numvar(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3385"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "MathProgBase.numlinconstr(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7.709557056427002"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "getsolvetime(m)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "In this case, the lower bound on the objective and the best value we found is the same (but it can be different if we set time or other user limits)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.171855696756295"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "getobjbound(m)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.171855696756295"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "getobjectivevalue(m)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:PerturbationParameters`\n",
    "\n",
    "Information on the family of perturbations we are searching over is stored in `:PerturbationParameters`. In this case, we are searching over additive perturbations, which is the default."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "additive"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d1[:PerturbationParameters]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Searching over different families of perturbations means different perturbation parameters are stored. In this case, we are working with a `5x5` blurring kernel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[36m[notice | MIPVerify]: Rebuilding model from scratch. This may take some time as we determine upper and lower bounds for the input to each non-linear unit. The model built will be cached and re-used for future solves, unless you explicitly set rebuild=false.\n",
      "\u001b[39m\u001b[36m[notice | MIPVerify]: Specifying conv2d constraints ... \n",
      "\u001b[39m\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [10]\n",
      "\u001b[39m"
     ]
    },
    {
     "data": {
      "text/plain": [
       "blur.(5, 5)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d2 = MIPVerify.find_adversarial_example(n1params, sample_image, 10, GurobiSolver(OutputFlag=0),\n",
    "    pp = MIPVerify.BlurPerturbationParameters((5, 5)))\n",
    "\n",
    "d2[:PerturbationParameters]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:TargetIndexes`\n",
    "\n",
    "The perturbed image is guaranteed to be classified in one of the target indexes. (Strictly speaking, we guarantee that the highest activation in the output layer among the target indexes exceeds the highest activation in the output layer among non-target indexes by at least the value of the `tolerance` passed in."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1-element Array{Int64,1}:\n",
       " 10"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d1[:TargetIndexes]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Multiple target labels and an inverted target selection are appropriately handled."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[36m[notice | MIPVerify]: Loading model from cache.\n",
      "\u001b[39m\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [2, 3, 4, 5, 6, 7, 9, 10]\n",
      "\u001b[39m"
     ]
    },
    {
     "data": {
      "text/plain": [
       "8-element Array{Int64,1}:\n",
       "  2\n",
       "  3\n",
       "  4\n",
       "  5\n",
       "  6\n",
       "  7\n",
       "  9\n",
       " 10"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d2 = MIPVerify.find_adversarial_example(n1params, sample_image, [1, 8], GurobiSolver(OutputFlag=0),\n",
    "    invert_target_selection = true)\n",
    "d2[:TargetIndexes]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:SolveStatus`\n",
    "\n",
    "This is the result of the solve. [More information on solve statuses](http://jump.readthedocs.io/en/latest/refmodel.html#solve-status)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "We typically find an optimal solution:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       ":Optimal"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d1[:SolveStatus]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "But we can encounter other solve statuses if (for instance) we set a time limit."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[36m[notice | MIPVerify]: Loading model from cache.\n",
      "\u001b[39m\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [2]\n",
      "\u001b[39m"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[1m\u001b[33mWARNING: \u001b[39m\u001b[22m\u001b[33mNot solved to optimality, status: UserLimit\u001b[39m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       ":UserLimit"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d2 = MIPVerify.find_adversarial_example(n1params, sample_image, 2, GurobiSolver(OutputFlag=0, TimeLimit=10))\n",
    "d2[:SolveStatus]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:Perturbation`\n",
    "\n",
    "This is the (pixel-wise) difference between the original image and the perturbed image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1×28×28×1 Array{Float64,4}:\n",
       "[:, :, 1, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 2, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 3, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "...\n",
       "\n",
       "[:, :, 26, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 27, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 28, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "perturbation = getvalue(d1[:Perturbation])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHAAAABwBAMAAAA0zul4AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAD1BMVEX5+PmKEA0JLFi53vf///9lXu7+AAAAAWJLR0QEj2jZUQAAAAd0SU1FB+ICFgEeGF4FhrQAAAA1SURBVFjD7dIhAQAgDADBVViFVVj/bngECsO48+8+AgA4yJwfAnBT1fyQXffk8KE1PQ0Af1vqRARBLlY/vgAAAABJRU5ErkJggg==",
      "text/plain": [
       "28×28 Array{RGB{Float64},2}:\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)  …  RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)  …  RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)  …  RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " ⋮                                         ⋱                                          \n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.723685,0.871963,0.968818)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)  …  RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)  …  RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)\n",
       " RGB{Float64}(0.974598,0.972607,0.975359)     RGB{Float64}(0.974598,0.972607,0.975359)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "view_diff(perturbation[1, :, :, 1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:PerturbedInput`\n",
    "\n",
    "This is the perturbed image."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1×28×28×1 Array{Float64,4}:\n",
       "[:, :, 1, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 2, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 3, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "...\n",
       "\n",
       "[:, :, 26, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 27, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0\n",
       "\n",
       "[:, :, 28, 1] =\n",
       " 0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  …  0.0  0.0  0.0  0.0  0.0  0.0  0.0"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "perturbed_input = getvalue(d1[:PerturbedInput])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAHAAAABwCAAAAADji6uXAAAABGdBTUEAALGPC/xhBQAAAAJiS0dEAP+Hj8y/AAAAB3RJTUUH4gIWAR4ZKQK2IgAAAXxJREFUaN7t2c8rBGEcx/E9cHRRkpNSlJtyclg5cJKLpDhxdZNwcXBG/gNXcXMXV06SkgNRKEX5GYks72/tU9M0trGe+UGf12nbefZ577RPu8/MFgoiIiIiIiIpG8cYBjCDIhTMV3AUC7DHNxHey15RwjPs+W00QMFsg0uwyUpV2kIjFMwueA574T52QhZRjDCPUwSjsRePgt6DbRhEHWJ/8GjBIVx0CgpmE/yNIbjgNRRUUMF0gxNYgQs+oRMKZhf8xHfHmjCNy4APhDdU91Awu2CUXsziBHE2xctQMB/BVmwivDDOsFfWD3tDR3DHbWFFzdcDBdMLTuIYNsEjLmCb3BE0Izx+Fzb2Ae1wz1f6IlEw2eA6bIINdKPS2A5cwcZXvYlS0HuwHnOIMza4EV6FgvkI/oTdOLLYLbqg4N8KHuANFlxD4menoHf242yxO6SyQhX0yjZU9ueKbZyGkfjZKehVLexi5gV2Yyjxs1PQuxrYhWcfEo8pKP/bFw+rnwoHRW1DAAAAAElFTkSuQmCC",
      "text/plain": [
       "28×28 Array{Gray{Float64},2}:\n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)  …  Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)  …  Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)  …  Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " ⋮                                       ⋱                         \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.250287)\n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)  …  Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)  …  Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     \n",
       " Gray{Float64}(0.0)  Gray{Float64}(0.0)     Gray{Float64}(0.0)     "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "colorview(Gray, perturbed_input[1, :, :, 1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "We can verify that the perturbed input is in fact the sample image added to the perturbation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "all(perturbed_input == sample_image + perturbation)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:Output`\n",
    "\n",
    "This is the calculated value of the activations of the final layer of the neural net with the perturbed input. Note that `output[10]` is (tied for) the largest element of the array, as we would expect with `tolerance=0`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Float64,1}:\n",
       " 0.388105\n",
       " 0.515855\n",
       " 1.25875 \n",
       " 0.296821\n",
       " 0.410448\n",
       " 0.556019\n",
       " 0.444605\n",
       " 3.49171 \n",
       " 0.412949\n",
       " 3.49171 "
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "output = getvalue(d1[:Output])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "We can verify that these activations are indeed accurate:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10-element Array{Float64,1}:\n",
       " 0.388105\n",
       " 0.515855\n",
       " 1.25875 \n",
       " 0.296821\n",
       " 0.410448\n",
       " 0.556019\n",
       " 0.444605\n",
       " 3.49171 \n",
       " 0.412949\n",
       " 3.49171 "
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "perturbed_input |> n1params"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "### `:BlurKernel`\n",
    "\n",
    "An additional entry for the blur kernel is stored when we are searching over only blurring perturbations."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[36m[notice | MIPVerify]: Loading model from cache.\n",
      "\u001b[39m\u001b[36m[notice | MIPVerify]: Attempting to find adversarial example. Neural net predicted label is 8, target labels are [10]\n",
      "\u001b[39m"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Dict{Symbol,Any} with 8 entries:\n",
       "  :PerturbationParameters => blur.(5, 5)\n",
       "  :TargetIndexes          => [10]\n",
       "  :SolveStatus            => :Optimal\n",
       "  :Output                 => JuMP.GenericAffExpr{Float64,JuMP.Variable}[-0.0120…\n",
       "  :BlurKernel             => JuMP.Variable[__anon__ __anon__ __anon__ __anon__ …\n",
       "  :Model                  => Minimization problem with:…\n",
       "  :Perturbation           => JuMP.GenericAffExpr{Float64,JuMP.Variable}[__anon_…\n",
       "  :PerturbedInput         => JuMP.Variable[__anon__ __anon__ __anon__ __anon__ …"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d_blur = MIPVerify.find_adversarial_example(n1params, sample_image, 10, GurobiSolver(OutputFlag=0),\n",
    "    pp = MIPVerify.BlurPerturbationParameters((5, 5)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5×5×1×1 Array{Float64,4}:\n",
       "[:, :, 1, 1] =\n",
       " 0.0  0.0        0.0       0.0  0.0\n",
       " 0.0  0.0        0.0       0.0  0.0\n",
       " 0.0  0.0        0.351349  0.0  0.0\n",
       " 0.0  0.0954499  0.256589  0.0  0.0\n",
       " 0.0  0.296612   0.0       0.0  0.0"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "getvalue(d_blur[:BlurKernel])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 0.6.0",
   "language": "julia",
   "name": "julia-0.6"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "0.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
